package com.huaxin.hxmodulesystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huaxin.hxmodulesystem.dto.ResponseCode;
import com.huaxin.hxmodulesystem.dto.ResponseResult;
import com.huaxin.hxmodulesystem.dto.request.AddOrganizationReqDTO;
import com.huaxin.hxmodulesystem.dto.request.UpdateOrganizationReqDTO;
import com.huaxin.hxmodulesystem.dto.response.GetOrganizationInfoRespDTO;
import com.huaxin.hxmodulesystem.dto.response.OrganizationTreeNodeDTO;
import com.huaxin.hxmodulesystem.mapper.OrganizationMapper;
import com.huaxin.hxmodulesystem.mapper.UserMapper;
import com.huaxin.hxmodulesystem.mapping.OrganizationMapping;
import com.huaxin.hxmodulesystem.models.Organization;
import com.huaxin.hxmodulesystem.models.User;
import com.huaxin.hxmodulesystem.service.OrganizationService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class OrganizationServiceImpl extends ServiceImpl<OrganizationMapper, Organization> implements OrganizationService {

    private final OrganizationMapping organizationMapping;

    private final CacheManager cacheManager;

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final ApplicationContext applicationContext;

    private final UserMapper userMapper;

    //添加组织
    @Override
    public Organization addOrganization(AddOrganizationReqDTO in) {
        if (in == null) {
            return null;
        }
        if (StringUtils.isBlank(in.getName())) {
            return null;
        }
        if (StringUtils.isBlank(in.getCode())) {
            return null;
        }
        if (StringUtils.isBlank(in.getAdminTel())) {
            return null;
        }
        QueryWrapper<Organization> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.eq("name", in.getName()).or().eq("code", in.getCode()));
        if (this.count(queryWrapper) > 0) {
            return null;
        }
        Organization organization = organizationMapping.toEntity(in);
        organization.setStatus(0);
        if (!this.save(organization)) {
            return null;
        }

        String id = organization.getId();
        if (id == null) {
            return null;
        }
        Organization respData = this.getById(id);
        if (respData == null) {
            return null;
        }
        Integer autoId = respData.getAutoId();
        if (autoId == null) {
            return null;
        }
        // 生成 org_number：格式为 yyyyMM + autoId（补足4位）
        String yearMonth = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        String paddedId = String.format("%04d", autoId); // 不足4位前面补0
        String orgNumber = yearMonth + paddedId;
        // 更新 org_number 字段
        respData.setOrgNumber(orgNumber);
        if (this.updateById(respData)) {
            return respData;
        } else {
            return null;
        }
    }

    /**
     * 根据组织ID获取组织信息
     *
     * @param id 组织ID
     * @return 组织基本信息
     */
    @Override
    public ResponseResult<Organization> getOrganizationById(String id) {
        if (StringUtils.isBlank(id)) {
            return ResponseResult.parameterError(null, "组织ID不能为空");
        }
        return ResponseResult.ok(this.getById(id));
    }

    /**
     * 修改组织
     *
     * @param in 修改组织入参
     * @return
     */
    @Override
    @CacheEvict(value = "organizationInfo", key = "#in.id")
    public ResponseResult<String> updateOrganization(UpdateOrganizationReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }
        if (StringUtils.isBlank(in.getId())) {
            return ResponseResult.parameterError(null, "组织ID不能为空");
        }
        if (StringUtils.isBlank(in.getName())) {
            return ResponseResult.parameterError(null, "组织名称不能为空");
        }
        if (StringUtils.isBlank(in.getCode())) {
            return ResponseResult.parameterError(null, "组织代码不能为空");
        }
        Organization organization = this.getById(in.getId());
        if (organization == null) {
            return ResponseResult.parameterError(null, "组织不存在");
        }
        organizationMapping.updateEntity(in, organization);
        if (this.updateById(organization)) {
            return ResponseResult.ok(null);
        } else {
            return ResponseResult.failure(ResponseCode.INTERNAL_ERROR, "修改组织失败，请稍后再试！", null);
        }
    }

    /**
     * 删除组织
     *
     * @param id 组织ID
     * @return
     */
    @Override
    @CacheEvict(value = "organizationInfo", key = "#id")
    public ResponseResult<String> deleteOrganization(String id) {
        if (StringUtils.isBlank(id)) {
            return ResponseResult.parameterError(null, "组织ID不能为空");
        }
        if (applicationContext.getBean(OrganizationService.class).removeById(id)) {
            return ResponseResult.ok(null);
        } else {
            return ResponseResult.failure(ResponseCode.INTERNAL_ERROR, "删除组织失败，请稍后再试！", null);
        }
    }

    /**
     * 获取组织列表
     *
     * @param pageNum  页码
     * @param pageSize 每页数量
     * @param search   搜索条件
     * @return
     */
    @Override
    public ResponseResult<Page<Organization>> getOrganizationList(Integer pageNum, Integer pageSize, String search) {
        Page<Organization> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Organization> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(search)) {
            wrapper.like("name", search)
                    .or()
                    .like("code", search)
                    .or()
                    .like("admin_tel", search);
        }
        return ResponseResult.ok(this.page(page, wrapper));
    }

    /**
     * 获取组织详情
     *
     * @param id 组织ID
     * @return
     */
    @Override
    @Cacheable(value = "organizationInfo", key = "#id", unless = "#result == null")
    public ResponseResult<GetOrganizationInfoRespDTO> getOrganizationDetail(String id) {
        if (StringUtils.isBlank(id)) {
            return ResponseResult.parameterError(null, "组织ID不能为空");
        }
        Organization organizationInfo = this.getById(id);
        if (organizationInfo == null) {
            return ResponseResult.notFound(null, "组织不存在");
        }
        GetOrganizationInfoRespDTO out = organizationMapping.toDTO(organizationInfo);
        if (out.getCreatedBy() != null) {
            User adminUser = userMapper.selectById(out.getCreatedBy());
            if (adminUser != null) {
                out.setAdminUserName(adminUser.getNickname());
            }
        }
        return ResponseResult.ok(out);
    }

    /**
     * 根据组织code获取组织信息
     *
     * @param code 组织code
     * @return
     */
    @Override
    public Organization getOrganizationByCode(String code) {
        QueryWrapper<Organization> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code);
        return this.getOne(queryWrapper);
    }

    /**
     * 绑定组织
     *
     * @param userId         用户ID
     * @param organizationId 组织ID
     * @return
     */
    @CacheEvict(value = "userInfo", key = "#userId")
    public ResponseResult<String> bindOrganization(String userId, String organizationId) {
        if (StringUtils.isBlank(userId)) {
            return ResponseResult.parameterError(null, "用户ID不能为空");
        }
        if (StringUtils.isBlank(organizationId)) {
            return ResponseResult.parameterError(null, "组织ID不能为空");
        }
        User user = userMapper.selectById(userId);
        if (user == null) {
            return ResponseResult.parameterError(null, "用户不存在");
        }
        user.setOrgId(organizationId);
        if (userMapper.updateById(user) > 0) {
            return ResponseResult.ok(null);
        } else {
            return ResponseResult.failure(ResponseCode.INTERNAL_ERROR, "绑定组织失败，请稍后再试！", null);
        }
    }

    /**
     * 解除组织绑定
     *
     * @param userId         用户ID
     * @param organizationId 组织ID
     * @return
     */
    @Override
    @CacheEvict(value = "userInfo", key = "#userId")
    public ResponseResult<String> unbindOrganization(String userId, String organizationId) {
        if (StringUtils.isBlank(userId)) {
            return ResponseResult.parameterError(null, "用户ID不能为空");
        }
        if (StringUtils.isBlank(organizationId)) {
            return ResponseResult.parameterError(null, "组织ID不能为空");
        }
        User user = userMapper.selectById(userId);
        if (user == null) {
            return ResponseResult.parameterError(null, "用户不存在");
        }
        user.setOrgId(null);
        if (userMapper.updateById(user) > 0) {
            return ResponseResult.ok(null);
        } else {
            return ResponseResult.failure(ResponseCode.INTERNAL_ERROR, "解除组织绑定失败，请稍后再试！", null);
        }
    }

    /**
     * 组织审核
     *
     * @param organizationId 组织ID
     * @param status         0-待审核 1-审核通过 2-审核未通过
     */
    @Override
    @CacheEvict(value = "organizationInfo", key = "#organizationId")
    public ResponseResult<String> auditOrganization(String organizationId, Integer status) {
        if (StringUtils.isBlank(organizationId)) {
            return ResponseResult.parameterError(null, "组织ID不能为空！");
        }
        if (status == null || status < 0 || status > 2) {
            return ResponseResult.parameterError(null, "状态不能为空！");
        }
        Organization organization = this.baseMapper.selectById(organizationId);
        if (organization == null) {
            return ResponseResult.failure(ResponseCode.INTERNAL_ERROR, "组织不存在！", null);
        }
        organization.setStatus(status);
        if (this.baseMapper.updateById(organization) > 0) {
            return ResponseResult.ok("操作成功！");
        } else {
            return ResponseResult.failure(ResponseCode.INTERNAL_ERROR, "操作失败！", null);
        }
    }

    //根据组织code判断组织是否存在]
    @Override
    public ResponseResult<Boolean> queryOrganizationExist(String code) {
        if (StringUtils.isBlank(code)) {
            return ResponseResult.parameterError(null, "参数错误！");
        }
        Organization organization = this.baseMapper.selectOne(new QueryWrapper<Organization>().eq("code", code));
        if (organization != null) {
            return ResponseResult.ok(true);
        } else {
            return ResponseResult.ok(false);
        }
    }

    /**
     * 获取组织树形结构（仅包含未删除且审核通过的组织）
     *
     * @return 组织树列表（森林）
     */
    @Override
    public List<OrganizationTreeNodeDTO> getOrganizationTree() {
        // 查询所有未删除的组织（可根据需要加 status = 1 审核通过）
        QueryWrapper<Organization> wrapper = new QueryWrapper<>();
        wrapper.eq("is_deleted", 0) // 未删除
                .orderByAsc("parent_id"); // 按 parent_id 排序有助于构建树

        List<Organization> allOrgs = this.list(wrapper);

        // 转换为 DTO 列表
        List<OrganizationTreeNodeDTO> nodes = allOrgs.stream().map(org -> {
            OrganizationTreeNodeDTO node = new OrganizationTreeNodeDTO();
            node.setId(org.getId());
            node.setName(org.getName());
            node.setCode(org.getCode());
            node.setParentId(org.getParentId());
            node.setStatus(org.getStatus());
            node.setAdminTel(org.getAdminTel());
            node.setAddress(org.getAddress());
            return node;
        }).collect(Collectors.toList());

        // 构建树结构
        return buildOrganizationTree(nodes);
    }

    /**
     * 构建组织树（将扁平列表构建成父子层级）
     */
    private List<OrganizationTreeNodeDTO> buildOrganizationTree(List<OrganizationTreeNodeDTO> nodes) {
        if (nodes == null || nodes.isEmpty()) {
            return new ArrayList<>();
        }

        // 使用 Map 提高查找效率：id -> node
        Map<String, OrganizationTreeNodeDTO> nodeMap = new HashMap<>();
        nodes.forEach(node -> nodeMap.put(node.getId(), node));

        List<OrganizationTreeNodeDTO> rootNodes = new ArrayList<>();

        for (OrganizationTreeNodeDTO node : nodes) {
            String parentId = node.getParentId();

            if (StringUtils.isBlank(parentId)) {
                // 是根节点
                rootNodes.add(node);
            } else {
                OrganizationTreeNodeDTO parentNode = nodeMap.get(parentId);
                if (parentNode != null) {
                    parentNode.getChildren().add(node);
                }
                // 如果 parent 不存在也不报错，只是不挂载
            }
        }

        return rootNodes;
    }

    /**
     * 获取指定组织及其所有子组织的 ID 集合（含自身）
     *
     * @param orgId 组织ID
     * @return 包含自身的所有子孙组织ID集合
     */
    @Override
    public Set<String> getOrgAndChildrenIds(String orgId) {
        if (StringUtils.isBlank(orgId)) {
            return Collections.emptySet();
        }

        Set<String> result = new HashSet<>();
        Queue<String> queue = new LinkedList<>(); // 使用队列进行广度优先搜索

        queue.offer(orgId);

        QueryWrapper<Organization> wrapper = new QueryWrapper<>();
        wrapper.select("id", "parent_id") // 只查需要的字段，提升性能
                .eq("is_deleted", 0)// 未删除
                .eq("status", 1);      // 审核通过

        List<Organization> allOrgs = this.list(wrapper);

        Map<String, List<String>> parentToChildrenMap = new HashMap<>();
        for (Organization org : allOrgs) {
            String parentId = org.getParentId();
            if (StringUtils.isNotBlank(parentId)) {
                parentToChildrenMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(org.getId());
            }
        }

        while (!queue.isEmpty()) {
            String currentId = queue.poll();
            result.add(currentId);

            List<String> children = parentToChildrenMap.get(currentId);
            if (children != null && !children.isEmpty()) {
                queue.addAll(children);
            }
        }

        return result;
    }
}